package com.asen.commons.core.jdbc.param;

import com.asen.commons.core.jdbc.handler.TypeHandler;
import com.asen.commons.core.meta.entity.EntityObject;
import com.asen.commons.core.meta.entity.FieldObject;
import com.asen.commons.core.meta.loader.EntityObjectLoader;
import com.asen.commons.utils.BaseAssert;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * SQL构建上下文
 *
 * @author Gary
 * @version 1.0
 * @date 2021-08-19
 */
public class SqlContext {

    private Class<?> mainClazz;

    private String modelType;

    private EntityObject mainEntity;

    private ParamStatementSetter paramSetter = new ParamStatementSetter();

    private List<String> columnList = new ArrayList<String>();

    protected StringBuilder joinSql = new StringBuilder();

    private int tableIndex = 1;

    /**
     * person ==> mainEntity
     */
    private Map<String, EntityObject> refEntityMap = new ConcurrentHashMap<String, EntityObject>();

    /**
     * person ==> t1
     */
    private Map<String, String> refAliasMap = new ConcurrentHashMap<String, String>();

    private Map<String, SqlColumn> sqlColumnMap = new ConcurrentHashMap<>();

    public SqlContext(Class<?> mainClazz) {
        this.mainClazz = mainClazz;
        this.modelType = mainClazz.getName();
        this.mainEntity = EntityObjectLoader.getInstance().load(mainClazz);
    }

    public void setParam(Class<?> javaType, String column, Object value, TypeHandler handler) {
        checkIfEmpty(column);
        if (columnList.contains(column)) {
            return;
        }
        columnList.add(column);
        paramSetter.setParam(javaType, value, handler);
    }

    public void setNull(Class<?> javaType, String column, TypeHandler handler) {
        checkIfEmpty(column);
        if (columnList.contains(column)) {
            return;
        }
        columnList.add(column);
        paramSetter.setNull(javaType, handler);
    }

    private void checkIfEmpty(String column) {
        BaseAssert.notEmpty(column, "参数不能为空");
    }

    public String getMainTable() {
        return mainEntity.getTable();
    }

    public List<String> getColumnList() {
        return columnList;
    }

    public boolean hasChangeColumns() {
        return columnList.size() > 0;
    }

    public String getJoinSql() {
        return joinSql.toString();
    }

    public void appendJoinSql(CharSequence sql) {
        joinSql.append(sql);
    }

    public List<FieldObject> getFieldList() {
        return mainEntity.getFieldList();
    }

    public FieldObject getMainField(String fieldName) {
        return mainEntity.getFieldObject(fieldName);
    }

    public int getTableIndexAndIncrement() {
        return tableIndex++;
    }

    public EntityObject getRefEntity(String refName) {
        return refEntityMap.get(refName);
    }

    public void putRefEntity(String refName, EntityObject entity) {
        refEntityMap.put(refName, entity);
    }

    public String getRefAlias(String refName) {
        return refAliasMap.get(refName);
    }

    public void putRefAlias(String refName, String alias) {
        refAliasMap.put(refName, alias);
    }

    public void putSqlColumn(String fullName, SqlColumn sqlColumn) {
        sqlColumnMap.put(fullName, sqlColumn);
    }

    public SqlColumn getSqlColumn(String fullName) {
        return sqlColumnMap.get(fullName);
    }

    public Class<?> getMainClazz() {
        return mainClazz;
    }

    public void setMainClazz(Class<?> mainClazz) {
        this.mainClazz = mainClazz;
    }

    public EntityObject getMainEntity() {
        return mainEntity;
    }

    public void setMainEntity(EntityObject mainEntity) {
        this.mainEntity = mainEntity;
    }

    public ParamStatementSetter getParamSetter() {
        return paramSetter;
    }

    public void setParamSetter(ParamStatementSetter paramSetter) {
        this.paramSetter = paramSetter;
    }
}
